home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / dict / _dp_hash.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  31.2 KB  |  1,402 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _dp_hash.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. //------------------------------------------------------------------------------
  17. // Dynamic Perfect Hashing  [DKMMRT]
  18. //
  19. // Michael Wenzel           ( 1990/91 ) 
  20. //
  21. //------------------------------------------------------------------------------
  22.  
  23.  
  24. #include <LEDA/impl/dp_hash.h>
  25.  
  26.  
  27.  
  28. // ----------------------------------------------------------------
  29. // allgemeine Funktionen und Konstanten
  30. // ----------------------------------------------------------------
  31.  
  32.  
  33. // Universum [1..dp_exp_31-1]
  34. // 2-er Potenzen, Shift Operationen sparen
  35. #define dp_exp_31 2147483648
  36. #define dp_exp_30 1073741824
  37. #define dp_exp_29 536870912 
  38. #define dp_exp_28 268435456 
  39. #define dp_exp_27 134217728 
  40. #define dp_exp_26 67108864 
  41. #define dp_exp_25 33554432 
  42.  
  43.  
  44. // Konstante fuer Groesse beim Rehashing 
  45. #define _dp_h_c 1
  46.  
  47. // allgmeine Quadrat- und Multiplikationsfunktion fuer 2-er Potenz
  48. #define sqr(x) ((x)*(x))                  
  49. #define mal_pot2(x,y) ((x)<<(y))
  50.  
  51. // Berechnung von (k*x)%p
  52. // fuer p=2^31+11  ( kleinste Primzahl > 2^31 )
  53.  
  54.  
  55. #define DPMOD_BODY(k,x,dp_erg)\
  56. { unsigned dp_k1=k>>16;\
  57.   unsigned dp_k2=k&65535;\
  58.   unsigned dp_x1=(unsigned(x))>>16;\
  59.   unsigned dp_x2=(unsigned(x))&65535;\
  60.   unsigned dp_e1=dp_k1*dp_x1+((dp_k1*dp_x2+dp_k2*dp_x1)>>16);\
  61.   unsigned dp_e2=dp_k2*dp_x2;\
  62.   unsigned dp_e3=((dp_k1*dp_x2+dp_k2*dp_x1)&65535)<<16;\
  63.   unsigned dp_e5=dp_e2+dp_e3;\
  64.   if ((dp_e2&dp_exp_31)&&(dp_e3&dp_exp_31))\
  65.     dp_e1++;\
  66.   else if (((dp_e2&dp_exp_31)||(dp_e3&dp_exp_31))&&(!(dp_e5&dp_exp_31)))\
  67.      dp_e1++; \
  68.   long dp_f=(dp_e5&0x7fffffff)-22*(dp_e1&0x03ffffff);\
  69.   if (dp_e1&dp_exp_26)\
  70.     if(dp_f<1476394997)\
  71.       dp_f+=671088651;\
  72.     else dp_f-=1476395008;\
  73.   if (dp_e1&dp_exp_27)\
  74.     if(dp_f<805306346)\
  75.       dp_f+=1342177302;\
  76.     else dp_f-=805306357;\
  77.   if (dp_e1&dp_exp_28)\
  78.     if(dp_f<1610612703)\
  79.       dp_f+=536870945;\
  80.     else dp_f-=1610612714;\
  81.   if (dp_e1&dp_exp_29)\
  82.     if(dp_f<1073741758)\
  83.       dp_f+=1073741890;\
  84.     else dp_f-=1073741769;\
  85.   if (dp_e1&dp_exp_30)\
  86.     if(dp_f<2147483527)\
  87.       dp_f+=121;\
  88.     else dp_f-=2147483538;\
  89.   if (dp_e5&dp_exp_31)\
  90.     if (dp_f<0)\
  91.       dp_f+=2147483648;\
  92.     else dp_f-=11;\
  93.   if (dp_f<0)\
  94.     dp_erg=unsigned(dp_f+2147483659);\
  95.   else  dp_erg=unsigned(dp_f);\
  96. }
  97.  
  98. #ifdef __TURBOC__
  99.  
  100. /* Function "dpmod"  */
  101.  
  102. static void dpmod(unsigned k, GenPtr x, unsigned& dp_erg) DPMOD_BODY(k,x,dp_erg)
  103.  
  104. #else
  105.  
  106. /* Macro "dpmod" */
  107.  
  108. #define dpmod(k,x,dp_erg) DPMOD_BODY(k,x,dp_erg)
  109.  
  110. #endif
  111.  
  112.  
  113. // ----------------------------------------------------------------
  114. // member-functions of class headertable 
  115. // ----------------------------------------------------------------
  116.  
  117. //-----------------------------------------------------------------
  118. // insert
  119. // fuegt ein Paar (Schluessel,Information) in das Bucket ein
  120. // berechnet Informationen neu
  121. // returns true, falls Element eingefuegt     
  122.  
  123.  
  124. bool headertable::insert(GenPtr a,GenPtr b,stp& erg,int& bed,bool& rehash,
  125.              stp anf,stp ende)
  126.   unsigned dp_erg=0;
  127.   if (!wj)                             // leere Headertable
  128.   { 
  129.     wj=1;
  130.  
  131.     if (!tj)
  132.     { 
  133.       mj=1;
  134.       tj=new subtable(a,b);            // einfach einfuegen
  135.       erg=tj;
  136.     }
  137.     else                               // Tafel war angelegt
  138.     {
  139.       if (mj==1)                       // nur einelementig  
  140.       {
  141.     tj->set_s(a,b);
  142.     erg=tj;
  143.       }
  144.       else                             // groessere Tafel
  145.         if (mj<=4)                     // nur 2 oder 4-elementig  
  146.         {
  147.       tj[0].set_s(a,b);
  148.           erg=tj;
  149.         }
  150.     else
  151.         {
  152.           dpmod(kj,a,dp_erg);
  153.           dp_erg=dp_erg%mal_pot2(sqr(mj),1);
  154.           tj[dp_erg].set_s(a,b);
  155.           erg=tj+dp_erg;
  156.         }
  157.     }
  158.    
  159.     bed+=2; 
  160.     rehash=false;
  161.     return true;         
  162.   }                                    // leere Tafel jetzt mit Element
  163.  
  164.   if (wj==1)                           // Tafel mit einem Element
  165.   { 
  166.     if (mj==1)
  167.     {
  168.       if (a==tj->ke)                   // gleiches Element
  169.       { 
  170.         tj->inf=b;
  171.         erg=tj;
  172.         rehash=false;
  173.         return false; 
  174.       }
  175.       else
  176.       { 
  177.         wj=2;                          // Einfuegen
  178.         bed+=6;
  179.         if (bed>=0)                    // Platz genug?
  180.         { 
  181.           rehash=true;
  182.           return true; 
  183.         }
  184.  
  185.         mj=2;                          // Speicher anfordern
  186.                        // und Elemente verteilen
  187.         stp lj=tj;
  188.         tj=new subtable[2];
  189.         tj[0] = (*lj);
  190.         tj[1].set_s(a,b);
  191.         erg = tj+1;
  192.     
  193.         if ((lj>ende)||(lj<anf)) 
  194.           delete lj;
  195.       }
  196.  
  197.       rehash = false;
  198.       return true;
  199.     }
  200.  
  201.     if (mj<=4)
  202.     {
  203.       if (a==tj[0].ke)               // gleiches Element
  204.       { 
  205.         tj[0].inf=b;
  206.         erg=tj;
  207.         rehash=false;
  208.         return false; 
  209.       }
  210.       else
  211.       { 
  212.     wj = 2;
  213.         bed+=6;
  214.     tj[1].set_s(a,b);
  215.         erg = tj+1;
  216.     rehash=false;
  217.     return true;
  218.       }
  219.     }
  220.     else                               // groessere Tafel
  221.     {
  222.       dpmod(kj,a,dp_erg);
  223.       dp_erg=dp_erg%mal_pot2(sqr(mj),1);
  224.  
  225.       if (a==tj[dp_erg].ke)            // gleiches Element
  226.       { 
  227.     tj[dp_erg].inf = b;
  228.     erg=tj+dp_erg;
  229.     rehash=false;
  230.     return false;
  231.       }
  232.  
  233.       wj=2;
  234.       bed+=6;
  235.  
  236.       if ( tj[dp_erg].ke == EMPTY )    // Position leer
  237.       { 
  238.         tj[dp_erg].set_s(a,b);
  239.         erg=tj+dp_erg;
  240.     rehash=false;
  241.     return true;
  242.       }
  243.       else                             // lokales Rehash
  244.       { 
  245.     stp lj = new subtable(tj[dp_erg]);
  246.     tj[dp_erg].clear();
  247.     int subsize = mal_pot2(sqr(mj),1);
  248.         int injektiv=0;            
  249.                        // injektive Funktion suchen
  250.     
  251.         while (!injektiv)
  252.         { injektiv=1;
  253.           kj=urandom(1,maxprim-1);
  254.  
  255.           unsigned dp_erg=0;
  256.           dpmod(kj,lj->ke,dp_erg);
  257.           dp_erg=dp_erg%subsize;
  258.           tj[dp_erg]=(*lj);
  259.  
  260.           dpmod(kj,a,dp_erg);
  261.           dp_erg=dp_erg%subsize;
  262.           if ( tj[dp_erg].ke == EMPTY )
  263.           {
  264.         tj[dp_erg].set_s(a,b);
  265.         erg=tj+dp_erg;
  266.           }
  267.           else
  268.           {
  269.             tj[dp_erg].clear(); 
  270.             injektiv=0;
  271.           }
  272.         }                              // Elemente injektiv verteilt 
  273.  
  274.         delete lj;
  275.         rehash=false;
  276.         return true;           
  277.       }
  278.     }
  279.   }                                    // Tafel enthaelt jetzt 2 Elemente
  280.  
  281.   if (wj<4)                            // Tafel mit 2 oder 3 Elementen
  282.   { 
  283.     for (int i1=0; i1<wj ; i1++)
  284.       if (a==tj[i1].ke)                // gleiches Element
  285.       { 
  286.         tj[i1].inf=b;
  287.         erg=tj+i1;
  288.         rehash=false;
  289.         return false; 
  290.       }
  291.  
  292.                        // neues Element
  293.     if (wj==2)
  294.       bed+=10;
  295.     else
  296.       bed+=14;
  297.  
  298.     if (mj==2)
  299.     {
  300.       if (bed>=0)                      // Platz genug?
  301.       { 
  302.         rehash=true;
  303.         return true; 
  304.       }
  305.  
  306.       mj=4;                            // Speicher anfordern
  307.       stp lj=tj;
  308.       tj=new subtable[4];
  309.  
  310.       for (int i1=0; i1<wj ; i1++)
  311.         tj[i1] = lj[i1];
  312.       tj[i1].set_s(a,b);
  313.       erg = tj+wj;
  314.     
  315.       if ((lj>ende)||(lj<anf)) 
  316.         delete lj;
  317.  
  318.       wj++;       
  319.       rehash = false;
  320.       return true;
  321.     }
  322.  
  323.     if (mj==4)
  324.     {
  325.       tj[wj].set_s(a,b);
  326.       erg = tj+wj;
  327.       wj++;       
  328.       rehash=false;
  329.       return true;
  330.     }
  331.     else                               // groessere Tafel
  332.     {
  333.       dpmod(kj,a,dp_erg);
  334.       dp_erg=dp_erg%mal_pot2(sqr(mj),1);
  335.       if ( tj[dp_erg].ke == EMPTY )    // Position leer
  336.       { 
  337.         tj[dp_erg].set_s(a,b);
  338.         erg=tj+dp_erg;
  339.         wj++;       
  340.     rehash=false;
  341.     return true;
  342.       }
  343.       else                             // lokales Rehash
  344.       {
  345.     stp lj = new subtable[++wj];
  346.         int i1=0;
  347.                                             // Elemente in Liste kopieren
  348.         for (int i2=0; i1<wj-1 ; i2++ )
  349.         { 
  350.       if ( tj[i2].ke != EMPTY  )
  351.           { 
  352.         lj[i1++]=tj[i2];  
  353.             tj[i2].clear(); 
  354.       }
  355.         }
  356.         lj[i1].set_s(a,b);
  357.  
  358.         int subsize = mal_pot2(sqr(mj),1);
  359.         int injektiv=0;                     // injektive Funktion suchen
  360.     
  361.         while (!injektiv)
  362.         { injektiv=1;
  363.           kj=urandom(1,maxprim-1);
  364.  
  365.           for (i1=0; (i1<wj) && injektiv ; i1++)
  366.           { 
  367.             dpmod(kj,lj[i1].ke,dp_erg);
  368.             dp_erg=dp_erg%subsize;
  369.  
  370.             if ( tj[dp_erg].ke == EMPTY )
  371.               tj[dp_erg]=lj[i1];
  372.             else
  373.             { 
  374.           injektiv=0;
  375.               for (int g=0;g<i1;g++)     // belegte Positionen loeschen
  376.               { 
  377.             GenPtr help=lj[g].ke;
  378.                 dpmod(kj,help,dp_erg);
  379.                 dp_erg=dp_erg%subsize;  
  380.                 tj[dp_erg].ke = EMPTY ; 
  381.                  }
  382.             }
  383.           }                            // Elemente injektiv verteilt  
  384.         }       
  385.  
  386.         delete lj;
  387.         rehash=false;
  388.         return true;           
  389.       }                                // lokales Rehash beendet
  390.     }
  391.   }                                    // Tafel enthaelt jetzt 2 oder 3 Elemente
  392.  
  393.   if (wj==4)                           // Tafel mit 4 Elementen
  394.   { 
  395.     for (int i1=0; i1<4; i1++)
  396.       if (a==tj[i1].ke)                // gleiches Element
  397.       { 
  398.         tj[i1].inf=b;
  399.         erg=tj+i1;
  400.         rehash=false;
  401.         return false; 
  402.       }
  403.   
  404.                        // neues Element einfuegen
  405.     bed+=18;
  406.  
  407.     if (bed>=0)                        // Platz genug?
  408.     { 
  409.       rehash=true;
  410.       return true; 
  411.     }
  412.  
  413.     mj=8;                               // Speicher anfordern
  414.                     // und Elemente verteilen
  415.     stp lj=tj;
  416.     tj=new subtable[128];
  417.     int injektiv=0;       
  418.                     // injektive Funktion suchen
  419.     
  420.     while (!injektiv)
  421.     {
  422.       injektiv=1;
  423.       kj=urandom(1,maxprim-1);
  424.  
  425.       for (int i1=0; (i1<4) && injektiv ; i1++)
  426.       { 
  427.         dpmod(kj,lj[i1].ke,dp_erg);
  428.         dp_erg=dp_erg%128;
  429.  
  430.         if ( tj[dp_erg].ke == EMPTY )
  431.           tj[dp_erg]=lj[i1];
  432.         else
  433.         { 
  434.       injektiv=0;
  435.           for (int g=0;g<i1;g++)     // belegte Positionen loeschen
  436.           { 
  437.         GenPtr help=lj[g].ke;
  438.             dpmod(kj,help,dp_erg);
  439.             dp_erg=dp_erg%128;  
  440.             tj[dp_erg].ke = EMPTY ; 
  441.              }
  442.         }
  443.       }
  444.       if (injektiv)                  // letztes Element hashen
  445.       {
  446.         dpmod(kj,a,dp_erg);
  447.         dp_erg=dp_erg%128;
  448.         if ( tj[dp_erg].ke == EMPTY )
  449.         { 
  450.           tj[dp_erg].set_s(a,b);
  451.           erg=tj+dp_erg;
  452.         }
  453.         else
  454.         { 
  455.           injektiv=0;
  456.           for (int g=0;g<i1;g++)     // belegte Positionen loeschen
  457.           { 
  458.             GenPtr help=lj[g].ke;
  459.             dpmod(kj,help,dp_erg);
  460.             dp_erg=dp_erg%128;  
  461.             tj[dp_erg].clear() ; 
  462.           }
  463.         }                            // letztes Element 
  464.       }             
  465.     }                                // Elemente injektiv verteilt 
  466.  
  467.     if ((lj>ende)||(lj<anf)) 
  468.       delete lj;
  469.  
  470.     wj=5;                          
  471.     rehash=false;
  472.     return true;           
  473.   }                             // Tafel enthaelt jetzt 5 Elemente
  474.  
  475.                                 // Tafel mit >= 5 Elementen
  476.                 // injektives Hashing auf Bucket
  477.  
  478.   int subsize=mal_pot2(sqr(mj),1);
  479.   dpmod(kj,a,dp_erg);
  480.   dp_erg=dp_erg%subsize;
  481.  
  482.   if ( tj[dp_erg].ke == a)         // gleiches Element
  483.   { 
  484.     tj[dp_erg].set_s(a,b);
  485.     erg=tj+dp_erg;
  486.     rehash=false;
  487.     return false;      
  488.   }
  489.  
  490.   int oldscard=wj;
  491.   int subcard=(++wj);
  492.   bed+=mal_pot2(subcard,2)-2;
  493.  
  494.   if ( tj[dp_erg].ke == EMPTY  )    // Position leer -> einfuegen
  495.   { 
  496.     tj[dp_erg].set_s(a,b);
  497.     erg=tj+dp_erg;
  498.     rehash = false;
  499.     return true; 
  500.   }
  501.   else                         // Tafelelement besetzt             
  502.    
  503.     if (subcard<=mj)           // aber noch Platz in Tafel
  504.     {  
  505.       stp lj = new subtable[subcard];
  506.       int i1=0;
  507.                                // Elemente in Liste kopieren
  508.       for (int i2=0; i1<oldscard  ; i2++ )
  509.       {
  510.     if ( tj[i2].ke != EMPTY  )
  511.         {
  512.           lj[i1++]=tj[i2];  
  513.           tj[i2].clear(); 
  514.         }
  515.       }
  516.       lj[i1].set_s(a,b);
  517.                                  // lokales Rehash , alle Elemente in Liste lj
  518.  
  519.       int injektiv=0;
  520.       while (!injektiv)          // injektive Funktion suchen
  521.       { 
  522.     injektiv=1;
  523.         kj=urandom(1,maxprim-1);
  524.  
  525.         for (i1=0; (i1<subcard) && injektiv ; i1++)
  526.         { 
  527.           dpmod(kj,lj[i1].ke,dp_erg);
  528.           dp_erg=dp_erg%subsize;
  529.           if ( tj[dp_erg].ke == EMPTY )
  530.           {
  531.             tj[dp_erg]=lj[i1]; 
  532.         erg=tj+dp_erg;
  533.           }
  534.           else
  535.           {
  536.         injektiv=0;                // Injektivitaet verletzt
  537.             for (int g=0;g<i1;g++)     // belegte Positionen loeschen
  538.             {
  539.           GenPtr help=lj[g].ke;
  540.           dpmod(kj,help,dp_erg);
  541.               dp_erg=dp_erg%subsize;  
  542.               tj[dp_erg].ke = EMPTY ; 
  543.                }
  544.           }
  545.         }                       // Elemente getestet
  546.  
  547.       }                         // naechster Versuch oder fertig
  548.  
  549.       delete lj;
  550.       rehash = false;
  551.       return true; 
  552.     }                             // subcard<=mj
  553.  
  554.     else                          // |Wj|>Mj , d.h. Groesse der
  555.                                 // Subtable verdoppeln
  556.     { 
  557.       if (bed>=0)                 // Kontrolle des Platzverbrauchs
  558.       {
  559.         rehash = true;
  560.         return true;    
  561.       }
  562.       else                        // Platz in Ordnung             
  563.                                   // Untertafel verdoppeln
  564.       { 
  565.         int oldssize= mal_pot2(sqr(mj),1);
  566.         int i1=0;
  567.                                   // Elemente in Liste retten
  568.         stp lj = new subtable[subcard]; 
  569.         for (int i2=0; i1<oldscard ; i2++)
  570.           if ( tj[i2].ke != EMPTY  )
  571.             lj[i1++]=tj[i2];
  572.         lj[i1].set_s(a,b);
  573.  
  574.         for ( ; mj<wj ; mj<<=1 ) ;    // Subtable vergroessern
  575.         subsize = mal_pot2(sqr(mj),1); 
  576.  
  577.         if ((tj>ende)||(tj<anf))      // Speicherverwaltung
  578.           delete tj;
  579.  
  580.         tj=new subtable[subsize]; 
  581.         int injektiv=0;
  582.                                       // injektive Funktion suchen
  583.         while (!injektiv)       
  584.         {
  585.           injektiv=1;
  586.           kj=urandom(1,maxprim-1);
  587.           for (i1=0; (i1<subcard) && injektiv ; i1++)
  588.           {
  589.             dpmod(kj,lj[i1].ke,dp_erg);
  590.             dp_erg=dp_erg%subsize;
  591.             if ( tj[dp_erg].ke == EMPTY )
  592.             { 
  593.               tj[dp_erg]=lj[i1]; 
  594.               erg=tj+dp_erg;
  595.             }
  596.  
  597.              else                       // Injektivitaet verletzt
  598.              {
  599.            injektiv=0;
  600.                for (int g=0;g<i1;g++)   // Subtables saeubern
  601.                {
  602.          GenPtr help=lj[g].ke;
  603.          dpmod(kj,help,dp_erg);
  604.                  dp_erg=dp_erg%subsize;
  605.          tj[dp_erg].ke = EMPTY ; 
  606.            }
  607.  
  608.          }
  609.           }                             // alle Elemente getestet
  610.  
  611.         }                               // naechster Versuch oder fertig
  612.  
  613.         delete lj;
  614.       rehash = false;
  615.     return true;
  616.       }
  617.     }
  618.   }                       // insert
  619.    
  620. //-----------------------------------------------------------------
  621. // dinsert
  622. // fuegt ein Paar (Schluessel,Information) in das Bucket ein
  623. // benutzt Informationen aus Konstruktor oder Rehash_all
  624. // gibt true zurueck, falls erfolgreich
  625.  
  626.  
  627. int headertable::dinsert(GenPtr a,GenPtr b,
  628.               stp ende,stp& wo,stp& erg)
  629.  
  630. {
  631.   if (mj==1)                    // nur ein Element in Tafel 
  632.   {                // und Tafel anlegen  
  633.     tj=wo;
  634.     wo++; 
  635.     tj->set_s(a,b);    
  636.     erg=tj;
  637.     return true;  
  638.   }                             // leere Tafel jetzt mit Element
  639.  
  640.   if (mj==2)                    // zwei Elemente in Tafel 
  641.   {
  642.     if (!tj)               // und Tafel anlegen
  643.     { 
  644.       wj=1;
  645.       tj=wo;
  646.       wo+=2; 
  647.       tj[0].set_s(a,b);    
  648.       erg=tj;
  649.       return true;  
  650.     }                           // leere Tafel jetzt mit Element
  651.     else
  652.     { 
  653.       if (a==tj[0].ke)
  654.       {
  655.     tj[0].inf = b;
  656.     erg = tj;
  657.     return false;
  658.       }
  659.       wj=2;
  660.       tj[1].set_s(a,b);
  661.       erg=tj+1;
  662.       return true;
  663.     }
  664.   }
  665.  
  666.   if (mj<=4)                    // max 4 Elemente in Tafel 
  667.   {
  668.     if (!tj)               // und Tafel anlegen
  669.     { 
  670.       wj=1;
  671.       tj=wo;
  672.       wo+=4; 
  673.       tj[0].set_s(a,b);    
  674.       erg=tj;
  675.       return true;  
  676.     }                           // leere Tafel jetzt mit Element
  677.     else
  678.     { 
  679.       for (int i1=0; i1<wj; i1++)
  680.         if (a==tj[i1].ke)
  681.         {
  682.       tj[i1].inf = b;
  683.       erg = tj+i1;
  684.       return false;
  685.         }
  686.  
  687.       tj[wj].set_s(a,b);
  688.       erg=tj+wj;
  689.       wj++;
  690.       return true;
  691.     }
  692.   }
  693.  
  694.  
  695.  
  696.   if (!tj)                      // Tafel muss angelegt werden
  697.                 // Tafel mit meheren Elementen
  698.                 // erstes Element kommt hinein
  699.   { 
  700.     int q=mal_pot2(sqr(mj),1);  // Platz anfordern aus Pool
  701.     tj=wo;
  702.     wo+=q; 
  703.     if (wo>ende+1)
  704.       error_handler(1,"memory allocation error");
  705.  
  706.     kj=urandom(1,maxprim-1);     // erstes Element einfuegen
  707.     unsigned dp_erg=0;
  708.     dpmod(kj,a,dp_erg);
  709.     dp_erg=dp_erg%q;
  710.     tj[dp_erg].set_s(a,b);
  711.     erg=tj+dp_erg;
  712.     wj = 1;                     // jetzt aktuelles wj
  713.     return true;       
  714.   }                             // leere Tafel jetzt mit 1.Element
  715.  
  716.                                 // Tafel ist schon angelegt und enthaelt Element
  717.                                 // Tafel bekommt mindestens 5 Elemente
  718.   unsigned dp_erg=0;
  719.   int subsize=mal_pot2(sqr(mj),1);
  720.   dpmod(kj,a,dp_erg);
  721.   dp_erg=dp_erg%subsize;
  722.  
  723.   if ( tj[dp_erg].ke == a)           // gleicher Schluessel
  724.   { 
  725.     tj[dp_erg].set_s(a,b);
  726.     erg=tj+dp_erg;
  727.     return false;      
  728.   }
  729.  
  730.   if ( tj[dp_erg].ke == EMPTY  )     // Position leer
  731.   { tj[dp_erg].set_s(a,b);   
  732.     erg=tj+dp_erg;
  733.   }
  734.  
  735.   else                          // Position besetzt -> lokales Rehash 
  736.   {  
  737.                 // Elemente sammeln
  738.      stp lj = new subtable[wj+1];
  739.      int i1=0;
  740.      int i2=0;
  741.      for (i2=0; i1<wj ; i2++)   // Elemente in Liste kopieren
  742.      { if ( tj[i2].ke != EMPTY  )
  743.        { lj[i1++]=tj[i2];  
  744.          tj[i2].clear() ; 
  745.        }
  746.      }
  747.  
  748.      lj[i1++].set_s(a,b);         // i1 = wj+1
  749.  
  750.                                   // lokales Rehash , alle Elemente in Liste lj
  751.      int injektiv=0;
  752.                                   // injektive Funktion suchen
  753.      while (!injektiv)         
  754.      {
  755.        injektiv=1;
  756.        kj=urandom(1,maxprim-1);
  757.  
  758.        for (i2=0; (i2<i1) && injektiv ; i2++)
  759.        { 
  760.          dpmod(kj,lj[i2].ke,dp_erg);
  761.      dp_erg=dp_erg%subsize;
  762.          if ( tj[dp_erg].ke == EMPTY )
  763.      {
  764.        tj[dp_erg]=lj[i2]; 
  765.        erg=tj+dp_erg;
  766.          }
  767.          else                      // Injektivitaet verletzt
  768.          {
  769.        injektiv=0;
  770.            for (int g=0;g<i2;g++)  // Subtables saeubern
  771.            {
  772.          GenPtr help=lj[g].ke;
  773.              unsigned dp_erg=0;
  774.          dpmod(kj,help,dp_erg);
  775.              dp_erg=dp_erg%subsize;
  776.              tj[dp_erg].ke = EMPTY ;
  777.        }
  778.          }
  779.        }                           // alle Elemente getestet 
  780.  
  781.      }                             // neuer Versuch oder fertig
  782.  
  783.      delete lj;
  784.   }
  785.  
  786.   wj++;                           // aktuelle Anzahl updaten
  787.   return true;
  788.  
  789. }
  790.  
  791.  
  792. // ----------------------------------------------------------------
  793. // lookup
  794. // sucht nach Eintrag mit Schluessel a
  795. // gibt Pointer auf Eintrag zurueck, falls gefunden
  796. // 0 sonst
  797.  
  798. stp headertable::lookup(GenPtr a)
  799.  
  800.    if (!wj)  return 0;              // Headertable leer
  801.  
  802.    if (mj==1)                       // Headertable einelementig
  803.    { 
  804.      if (a==tj->ke) 
  805.        return tj;
  806.      else
  807.        return 0;
  808.    }
  809.  
  810.    if (mj<=4)                       // Tafel mit max 4 Elementen
  811.    { 
  812.      for (int i1=0; i1<wj; i1++)
  813.        if (a==tj[i1].ke) 
  814.          return tj+i1;
  815.      return 0;
  816.    }
  817.                                     // Headertable mit mehr als 4 Subtables
  818.    unsigned dp_erg=0;
  819.    dpmod(kj,a,dp_erg);
  820.    dp_erg=dp_erg%(mal_pot2(sqr(mj),1));   // Position
  821.  
  822.    if (tj[dp_erg].ke==a)
  823.      return tj+dp_erg;
  824.    else
  825.      return 0; 
  826.  } 
  827.  
  828. // ----------------------------------------------------------------
  829. // del
  830. // loescht Element in Tafel
  831. // gibt true zurueck, wenn erfolgreich
  832.  
  833. bool headertable::del(GenPtr a,stp anf,stp ende)
  834.  
  835. {
  836.   if (!wj) return false;             // leere Headertable
  837.  
  838.   if (mj==1)                         // Headertable einelementig
  839.   { 
  840.     if (a==tj->ke) 
  841.     {
  842.       wj=0;                          // Schluessel gefunden
  843.       tj->clear() ;
  844.       if ((tj<anf)||(tj>ende))
  845.       {
  846.     delete tj;
  847.     tj = 0;
  848.     mj = 0;
  849.       } 
  850.       return true;    
  851.     }
  852.     else
  853.       return false;
  854.   }
  855.      
  856.   if (mj<=4)           
  857.   { 
  858.     if (wj>1)                        // Headertable mit mind 2 Elementen
  859.     {
  860.       for (int i1=0; i1<wj; i1++)
  861.       { 
  862.     if (tj[i1].ke==a)            // Element gefunden
  863.         { 
  864.           wj--;
  865.           tj[i1]=tj[wj];             // Loch fuellen
  866.           tj[wj].clear();
  867.           return true;
  868.         }
  869.       }
  870.       return false;
  871.     }
  872.     else                               // ein Element in Bucket
  873.     {
  874.       if (tj[0].ke==a) 
  875.       {
  876.     wj=0;                          // Schluessel gefunden
  877.         tj[0].clear() ;
  878.         if ((tj<anf)||(tj>ende))
  879.         {
  880.       delete tj;
  881.       tj = 0;
  882.       mj = 0;
  883.         } 
  884.         return true;    
  885.       }
  886.       else
  887.         return false;
  888.     }
  889.   }
  890.      
  891.                       // Headertable mit mehreren Subtables
  892.   unsigned dp_erg=0;
  893.   dpmod(kj,a,dp_erg);
  894.   dp_erg=dp_erg%(mal_pot2(sqr(mj),1));   // Position
  895.  
  896.   if (tj[dp_erg].ke==a)
  897.   {
  898.     wj--;                             // Schluessel gefunden
  899.     tj[dp_erg].clear() ;
  900.  
  901.     if (wj==0)                        // Bucket nun leer
  902.       if ((tj<anf)||(tj>ende))
  903.       {
  904.     delete tj;
  905.     tj = 0;
  906.     mj = 0;
  907.       } 
  908.     return true;    
  909.   } 
  910.   else return false;
  911. }
  912.  
  913. // ---------------------------------------------------------
  914. // give_elements()
  915. // haengt Elemente der Tafel an Liste an
  916. // gibt Anzahl der Elemente zurueck
  917.  
  918.  
  919. int headertable::give_elements(stp& wo,stp anf,stp ende)
  920.  
  921.   int j=0;
  922.  
  923.   if (!wj) { 
  924.          if ( tj && ((tj<anf)||(tj>ende))) 
  925.              {
  926.            if (mj>1)
  927.                  delete tj;
  928.            else 
  929.                  delete tj;
  930.  
  931.            tj = 0;
  932.            mj = 0;
  933.              }
  934.          return 0;
  935.        }
  936.  
  937.   if (mj==1)                    // Headertable einelementig
  938.   { 
  939.     (*wo)=(*tj);                // Element kopieren
  940.     wo++;
  941.     if ((tj<anf)||(tj>ende))     // gebe Speicher frei
  942.     {
  943.       delete tj;
  944.       tj = 0;
  945.       mj = 0;
  946.     }
  947.     return 1; 
  948.   }
  949.  
  950.   if (mj<=4)                     // Headertable maximal vierelementig
  951.   { 
  952.     j=0;   
  953.     while ( (tj[j].ke != EMPTY) && (j<mj) )
  954.     { 
  955.       (*wo)=tj[j];
  956.       wo++;
  957.       j++;
  958.     }
  959.  
  960.     if ((tj<anf)||(tj>ende))     // gebe Speicher frei
  961.     { 
  962.       delete tj;
  963.       tj = 0;
  964.       mj = 0;
  965.     }
  966.     return j; 
  967.   }
  968.  
  969.                  // Headertable mit meheren Elementen
  970.   bool weiter=true;
  971.   int subsize=mal_pot2(sqr(mj),1);
  972.   j=0;
  973.  
  974.   for (int k=0;(k<subsize)&&weiter;k++)  // suche Elemente
  975.     if ( tj[k].ke != EMPTY  )
  976.     {                                    // haenge Element an Liste
  977.       (*wo)=tj[k];
  978.       wo++; j++;
  979.       if (j>=wj) weiter=false; 
  980.     }
  981.   if ((tj<anf)||(tj>ende))               // gebe Speicher frei
  982.   { 
  983.     delete tj;
  984.     tj = 0;
  985.     mj = 0;
  986.   }
  987.   return j;
  988. }
  989.  
  990. // ----------------------------------------------------------------
  991. // member-functions of class dp_hash
  992. // ----------------------------------------------------------------
  993.  
  994. // -------------------------------------------------------
  995. // rehash_all
  996. //
  997. // stellt Headertables neu auf, um Platzverbrauch korrekt
  998. // zu halten
  999. // fuegt Element dann neu ein
  1000.  
  1001. stp dp_hash::rehash_all( GenPtr x=EMPTY , GenPtr y=0 )
  1002.  
  1003.   int i,i1,j,nsave,platz;
  1004.   unsigned dp_erg=0;
  1005.  
  1006.   stp erg=0;
  1007.   stp l=new subtable[n];         // Sammle Elemente in Liste l
  1008.  
  1009.   i=0;
  1010.   stp pos = l;
  1011.   nsave = ( x == EMPTY ? n : n-1 );
  1012.  
  1013.   while ( (i<sM) && (nsave>0) )  // Sammle Element aus allen Headertables
  1014.   { 
  1015.     if (htablep[i])
  1016.     {
  1017.       nsave -= htablep[i]->give_elements(pos,anf,ende) ;
  1018.       delete htablep[i];
  1019.     }
  1020.     i++;   
  1021.   }
  1022.  
  1023.   if ( x != EMPTY )               // fuege neues Element hinzu
  1024.     l[n-1].set_s(x,y);
  1025.  
  1026.   free ((char*)htablep);          // Speicher freigeben
  1027.   if (anf) 
  1028.     delete anf; 
  1029.                         // neue Parameter setzen
  1030.  
  1031.   M=int((1+_dp_h_c)*n);
  1032.   sM = int(((4.0/3.0)*wursechs)*(1+_dp_h_c)*n);
  1033.  
  1034.                                   // Speicher allokieren
  1035.   htablep=(htp*) calloc(sM,sizeof(htp));  // schneller als new+init
  1036.   int* buckets=new int[n];
  1037.  
  1038.   if (!htablep)
  1039.     error_handler(1,"memory overflow");
  1040.  
  1041.   platz=n;
  1042.   i1=0;
  1043.   while (!i1)                    // Top-Funktion suchen
  1044.   { 
  1045.     bed=0;
  1046.     k=urandom(1,maxprim-1);
  1047.     for (i=0;i<n;i++)           // Hashe alle Elemente
  1048.     {
  1049.       GenPtr help=l[i].ke;
  1050.       dpmod(k,help,dp_erg);
  1051.       dp_erg=dp_erg%sM;
  1052.       buckets[i] = dp_erg;      // Merke Headertable
  1053.  
  1054.       if (!htablep[dp_erg]) 
  1055.         htablep[dp_erg] = new headertable;
  1056.  
  1057.                                 // Aendere Headertables
  1058.       int f=++(htablep[dp_erg]->wj);
  1059.       int* groesse=&(htablep[dp_erg]->mj);
  1060.  
  1061.       if (f<=2)
  1062.      (*groesse)++;
  1063.       else
  1064.         if (*groesse<f)
  1065.         { 
  1066.       (*groesse)<<=1;      
  1067.   
  1068.       if (*groesse==4)       // vergroessere Feld
  1069.         platz++;
  1070.           else
  1071.         if (*groesse==8)     // Uebergang von Feld auf Tafel
  1072.           platz+=123;
  1073.             else
  1074.           platz+=3*sqr(*groesse)/2; 
  1075.         }
  1076.     else                     // Tafel nicht vergroessert
  1077.       platz--;
  1078.  
  1079.       bed+=mal_pot2(f,2)-2; 
  1080.     }                            // alle Elemente gehasht
  1081.  
  1082.                                  // bed-=(((8.0*sqr(M))/sM)+2*M);
  1083.     float _bed=(wursechs+2)*M;   // Vereinfachung durch Einsetzen von sM
  1084.     bed-=int(_bed);
  1085.     i1=(bed<0);                  // kontrolliere Platz
  1086.  
  1087.     if (!i1)                     // nicht erfolgreich, saeubere Headertables
  1088.     {
  1089.       platz=n;
  1090.       for (j=0; j<sM; j++)
  1091.         if (htablep[j]) 
  1092.     { 
  1093.       delete htablep[j];
  1094.       htablep[j] = 0 ;   
  1095.     }
  1096.     }
  1097.  
  1098.   }                              // Top-Funktion gefunden
  1099.  
  1100.  
  1101.   anf=new subtable[platz];        // allokiere Speicher fuer alle Subtables
  1102.   wo=anf;
  1103.   ende=anf+platz-1;
  1104.  
  1105.   for (i=0; i<n; i++)             // fuege Elemente wieder ein
  1106.   { 
  1107.     int bucket=buckets[i];  
  1108.     htablep[bucket]->dinsert(l[i].ke,l[i].inf,ende,wo,erg);
  1109.   }
  1110.  
  1111.   delete buckets;
  1112.   delete l;
  1113.   return erg;
  1114. }
  1115.  
  1116. // --------------------------------------------------------
  1117. // insert
  1118. //
  1119. // fuegt Element in die entsprechende Headertable ein
  1120.  
  1121. stp dp_hash::insert(GenPtr x,GenPtr y)
  1122.  
  1123.   if ( (unsigned)x>maxuni )  
  1124.     error_handler(2,string("dp_hash: key %d out of range",x));
  1125.  
  1126.   copy_key(x);
  1127.   copy_inf(y);
  1128.  
  1129.   unsigned dp_erg=0;
  1130.   dpmod(k,x,dp_erg);
  1131.   dp_erg=dp_erg%sM;                   // Toptafel
  1132.  
  1133.   bool rehash = false;
  1134.   stp  erg    = 0;
  1135.  
  1136.   if ( !htablep[dp_erg] ) 
  1137.     htablep[dp_erg] = new headertable;
  1138.  
  1139.   if ( htablep[dp_erg]->insert(x,y,erg,bed,rehash,anf,ende) )  n++;
  1140.  
  1141.   if ( rehash )  erg=rehash_all(x,y);
  1142.  
  1143.   return erg;
  1144. }
  1145.  
  1146. // --------------------------------------------------------
  1147. // del
  1148. //
  1149. // loescht Element aus entsprechender Headertable
  1150.  
  1151. void dp_hash::del(GenPtr x)
  1152.  
  1153.  
  1154.   if ( (unsigned)x>maxuni )  
  1155.     error_handler(2,string("key %d out of range",x));
  1156.  
  1157. // s.n. :
  1158.  
  1159. stp p = lookup(x);
  1160. if (p==0) return;
  1161. clear_key(p->ke);
  1162. clear_inf(p->inf);
  1163.  
  1164.  
  1165.   unsigned dp_erg=0;
  1166.   dpmod(k,x,dp_erg);
  1167.   dp_erg=dp_erg%sM;                   // Toptafel
  1168.  
  1169.   if ( !htablep[dp_erg] ) return;     // Headertable nicht vorhanden
  1170.                         // in Toptafel loeschen
  1171.  
  1172.   if ( htablep[dp_erg]->del(x,anf,ende) ) n--;     
  1173.  
  1174.   if ( !htablep[dp_erg]->wj )
  1175.   { 
  1176.     delete htablep[dp_erg];
  1177.     htablep[dp_erg] = 0;
  1178.   }
  1179.  
  1180.   if ((n*(1+3*_dp_h_c)<M) && (n>3))
  1181.     rehash_all(); 
  1182.  
  1183.  
  1184. // -------------------------------------------------------
  1185. // lookup,change_inf
  1186. //
  1187. // suchen in Headertable nach Element mit Schluessel
  1188. // change_inf setzt Information des Elementes auf y
  1189.  
  1190.  
  1191. stp dp_hash::lookup(GenPtr x) const 
  1192.  
  1193.   if ( (unsigned)x>maxuni )  
  1194.     error_handler(2,string("key %d out of range",x));
  1195.  
  1196.   unsigned dp_erg=0;
  1197.   dpmod(k,x,dp_erg);
  1198.   dp_erg=dp_erg%sM;                   // Toptafel
  1199.  
  1200.   if (!htablep[dp_erg]) 
  1201.     return 0;
  1202.  
  1203.   stp y=htablep[dp_erg]->lookup(x);
  1204.   return y ;
  1205.  
  1206. }
  1207.  
  1208. stp dp_hash::change_inf(GenPtr x,GenPtr y)      
  1209.   if ( (unsigned)x>maxuni )  
  1210.     error_handler(2,string("key %d out of range",x));
  1211.  
  1212.   unsigned dp_erg=0;
  1213.   dpmod(k,x,dp_erg);
  1214.   dp_erg=dp_erg%sM;                   // Toptafel
  1215.  
  1216.  
  1217.   if (!htablep[dp_erg])
  1218.     return 0;
  1219.  
  1220.   stp t = htablep[dp_erg]->lookup(x) ;
  1221.   if (t)
  1222.     t->inf = y ;
  1223.   return t;
  1224.  
  1225. }
  1226.  
  1227. // -------------------------------------------------------
  1228. // clear
  1229. //
  1230. // loescht alle Elemente und
  1231. // setzt Hashing auf Leerzustand
  1232.  
  1233. void dp_hash::clear()
  1234.  
  1235.   stp l = new subtable[n];
  1236.   stp pos=l;
  1237.  
  1238.   for (int i=0;i<sM;i++)           // Headertables loeschen
  1239.     if (htablep[i])
  1240.     { 
  1241.       htablep[i]->give_elements(pos,anf,ende);
  1242.       delete htablep[i];                         
  1243.     }
  1244.  
  1245.   free ((char*)htablep) ;          // Speicher freigeben
  1246.  
  1247.   if (anf) 
  1248.     delete anf;
  1249.  
  1250.   delete l;
  1251.  
  1252.   n = 0;                           // Leerinitialisierung
  1253.   M=4;
  1254.   sM=13;
  1255.   k=urandom(1,maxprim-1);
  1256.   bed=-17;
  1257.   htablep=(htp*) calloc(sM,sizeof(htp));
  1258.   anf = wo = ende = 0;
  1259.  
  1260. }
  1261.  
  1262. // ------------------------------------------------------------
  1263. // Konstruktoren und Destruktor
  1264.  
  1265. dp_hash::dp_hash()
  1266.  
  1267.   n=0;
  1268.   M=4;
  1269.   sM=13;
  1270.   k=urandom(1,maxprim-1);
  1271.   bed=-17;
  1272.   htablep=(htp*) calloc(sM,sizeof(htp));
  1273.   anf = wo = ende = 0;
  1274.  
  1275. }
  1276.  
  1277. dp_hash::dp_hash(int an,GenPtr* keys,GenPtr* inhalte)   
  1278.                                           // wie rehash_all
  1279.                                           // die Elemente stehen aber schon in Listen
  1280.   int i,i1,j,nsave,platz;
  1281.   unsigned dp_erg=0;
  1282.   stp erg=0;
  1283.  
  1284.   n=an;
  1285.   M=int((1+_dp_h_c)*n);
  1286.   sM = int(((4.0/3.0)*wursechs)*(1+_dp_h_c)*n);
  1287.  
  1288.   htablep=(htp*) calloc(sM,sizeof(htp));
  1289.   int* buckets = new int[n];
  1290.  
  1291.   if (!htablep)
  1292.     error_handler(1,"memory overflow");
  1293.  
  1294.   platz=n;
  1295.   i1=0;
  1296.  
  1297.   while (!i1)
  1298.   {
  1299.     bed=0;
  1300.     k=urandom(1,maxprim-1);
  1301.  
  1302.     for (i=0;i<n;i++)
  1303.     {
  1304.       GenPtr help=keys[i];
  1305.       if ( (unsigned)help>maxuni )  
  1306.          error_handler(2,string("key %d out of range",help));
  1307.  
  1308.       dpmod(k,help,dp_erg);
  1309.       dp_erg=dp_erg%sM;
  1310.       buckets[i] = dp_erg;
  1311.  
  1312.       if (!htablep[dp_erg]) 
  1313.     htablep[dp_erg] = new headertable;
  1314.  
  1315.       int f=++(htablep[dp_erg]->wj);
  1316.       int* groesse=&(htablep[dp_erg]->mj);
  1317.  
  1318.       if (f<=2)
  1319.      (*groesse)++;
  1320.       else
  1321.         if (*groesse<f)
  1322.         { 
  1323.       (*groesse)<<=1;      
  1324.   
  1325.       if (*groesse==4)       // vergroessere Feld
  1326.         platz++;
  1327.           else
  1328.         if (*groesse==8)     // Uebergang von Feld auf Tafel
  1329.           platz+=123;
  1330.             else
  1331.           platz+=3*sqr(*groesse)/2; 
  1332.         }
  1333.     else                     // Tafel nicht vergroessert
  1334.       platz--;
  1335.  
  1336.       bed+=mal_pot2(f,2)-2; 
  1337.     }
  1338.     
  1339.                                  // bed-=(((8.0*sqr(M))/sM)+2*M);
  1340.     float _bed=(wursechs+2)*M;   // Vereinfachung durch Einsetzen von sM
  1341.     bed-=int(_bed);
  1342.     i1=(bed<0);
  1343.  
  1344.     if (!i1)
  1345.     { 
  1346.       platz=n;
  1347.       for (j=0; j<sM; j++)
  1348.     if (htablep[j]) 
  1349.     { 
  1350.       delete htablep[j];
  1351.       htablep[j] = 0;   
  1352.     }
  1353.     }
  1354.   }
  1355.  
  1356.   nsave=an;
  1357.   anf=new subtable[platz];
  1358.  
  1359.   wo=anf;
  1360.   ende=wo+platz-1;
  1361.   n=0;
  1362.  
  1363.   for (i=0; i<nsave; i++)
  1364.   {
  1365.     int bucket = buckets[i];
  1366.     n += (htablep[bucket]->dinsert(keys[i],inhalte[i],ende,wo,erg));
  1367.   } 
  1368.  
  1369.   delete buckets;
  1370.  
  1371.   if ((n*(1+3*_dp_h_c)<M) && (n>3))
  1372.     rehash_all();   
  1373.  
  1374. }
  1375.  
  1376. dp_hash::~dp_hash()
  1377.   clear();                            // loesche alles
  1378.  
  1379.   free ((char*)htablep);              // gebe Speicher frei
  1380.   if (anf) delete anf;
  1381.  
  1382.   n=M=sM=0;
  1383.   k=0;
  1384.   anf=wo=ende=0;
  1385.   htablep=0;
  1386.  
  1387. }
  1388.